;
; vmscr.asm
;

include vmbdoor.inc

; enable x486 instructions, but use 16 bit segment
.486
option segment:use16

; code segment
codes	segment para use16 public 'CODE'
codes	ends

; data segment
datas	segment byte use16 public 'DATA'
BDOOR_MAGIC	dword  	VMWARE_MAGIC
BDOOR_PORT  	word	VMWARE_PORT
MSG_DISABLED	byte	'Copy & paste is disabled.$'
MSG_VMNG	byte	'Not running inside VMware.$'
END_OF_LINE	byte	CR, LF, '$'
READ_BUFFER	byte	?			; tail of data segment
; this address through DS:0ffffh should be available for *.com program
datas	ends

main	group codes,datas

codes	segment
; for tiny memory model (.com), all seg is the same
assume	cs:main,ds:main,es:main,ss:main
org	100h
entry:
check_vm	proc near
	; Check if we are running inside VMware
	xor 	ecx,ecx
	mov 	cl, VMCMD_GET_VERSION
	call	backdoor

	cmp	ebx,[BDOOR_MAGIC]
	jne	not_in_vm

	; Check if copy & paste is enabled
	mov	cl, VMCMD_GET_SETTING
	call	backdoor

	and	eax, VMPREF_COPY_PASTE
	jz	disabled
check_vm	endp

;************************************************
; copy operation
;************************************************
do_copy		proc near
	; get current curosr position
	mov 	ah, 03h
	xor 	bh, bh
	int 	10h
	push	dx

	xor	dx, dx				; row:col = 0:0
	mov	di, offset READ_BUFFER

next_char:
	call	getchar				; get a character
	cld
	stosb					; mov es:[di], al & inc di

	inc	dl
	cmp	dl, 80				; 1 row finished?
	jb	next_char			; no.

	; remove trailing blank
next_blank:
	mov	al, [di - 1]
	cmp	al, ' '
	jne	add_lf

	dec	di
	jmp	next_blank

	; supply LF to each line
add_lf:
	mov	al, LF
	stosb

	; next row
	xor	dl, dl
	inc	dh
	cmp	dh, 25				; all row finished?
	jb	next_char			; no.

	; restore original cursor position
	pop	dx
	call	getchar

send_data:
	sub	di, offset READ_BUFFER		; get data length
	jz	terminate			; no data. return to DOS

	; send data length
	xor	ebx, ebx
	mov	bx, di
	xor	ecx, ecx
	mov	cl, VMCMD_SET_CLIPLEN
	call	backdoor

	mov	ax, di
	mov	si, offset READ_BUFFER

next_data:
	push	ax				; store data length

	cld
	lodsd					; mov eax, ds:[si] & inc si
	mov	ebx, eax
	xor	ecx, ecx
	mov	cl, VMCMD_SET_CLIPDATA
	call	backdoor

	pop	ax				; retrieve length
	cmp	ax, 4				; more data?
	jbe	terminate			; no.  return to DOS

	sub	ax, 4
	jmp	next_data
do_copy		endp

;************************************************
; terminate routines
;************************************************

disabled:
	mov	dx, offset MSG_DISABLED		; disabled message
	jmp	print_msg

not_in_vm:
	mov	dx, offset MSG_VMNG		; not in VM message

print_msg:
	mov 	ah, 09h				; print function 
	int	21h				; DOS function call

	mov	dx, offset END_OF_LINE
	int	21h

	xor	al, al				; return code = 0

terminate:					; Now Return to DOS
	mov	ah, 4ch
	int	21h
	; this function call never returnes

;************************************************
; executes vmware backdoor i/o
;************************************************
backdoor	proc near
        mov	eax, [BDOOR_MAGIC]
        mov	dx, [BDOOR_PORT]
        in	eax, dx
	ret
backdoor	endp

;************************************************
; get character from screen
;************************************************
; dx = cursor positioon row:col
getchar	proc near
	; set cursor position
	mov ah, 02h
	xor bh, bh
	int 10h
	
	; read character at the cursor position
	mov ah, 08h
	xor bh, bh
	int 10h
	ret
getchar	endp

codes	ends
end	entry
; end of file
